﻿using System;
using System.Linq;
using System.Collections.Generic;

using Flagwind.Data;
using Flagwind.Common;
using Flagwind.ComponentModel;
using Flagwind.ComponentModel.DataAnnotations;

namespace Flagwind.ComponentModel
{
	public class SearchParameter : DataObject
	{
		/// <summary>
		/// 从1开始的页码。
		/// </summary>
		[RequiredValidator(RuleName = "paging")]
		[RangeValidator(1, 999, RuleName = "paging")]
		public int? PageIndex
		{
			get;
			set;
		}

		/// <summary>
		/// 页面大小。
		/// </summary>
		[RequiredValidator(RuleName = "paging")]
		[RangeValidator(1, 100, RuleName = "paging")]
		public int? PageSize
		{
			get;
			set;
		}
	}

	public abstract class SearchParameter<F, S, I> : SearchParameter, ISearchParameter<F, S, I> where F : struct where S : struct where I : struct
	{
		#region 私有字段

		private readonly List<Condition<F>> _conditions = new List<Condition<F>>();
		private readonly List<Sorting<S>> _sortings = new List<Sorting<S>>();
		private readonly List<I> _includes = new List<I>();

		#endregion

		#region 公共属性

		/// <summary>
		/// 获取查询条件。
		/// </summary>
		public IReadOnlyList<Condition<F>> Conditions
		{
			get
			{
				return _conditions;
			}
		}

		/// <summary>
		/// 获取排序规则。
		/// </summary>
		public IReadOnlyList<Sorting<S>> Sortings
		{
			get
			{
				return _sortings;
			}
		}

		/// <summary>
		/// 获取附加成员。
		/// </summary>
		public IReadOnlyList<I> Includes
		{
			get
			{
				return _includes;
			}
		}

		/// <summary>
		/// 获取或设置查询条件的组合方式。
		/// </summary>
		public ConditionCombination CombineMode
		{
			get;
			set;
		}

		#endregion

		#region 构造方法

		/// <summary>
		/// 初始化 <see cref="SearchParameter"/> 类的新实例。
		/// </summary>
		public SearchParameter()
		{
			this.CombineMode = ConditionCombination.And;
		}

		#endregion

		#region 查询条件

		/// <summary>
		/// 添加一个查询条件。
		/// </summary>
		/// <param name="member">条件成员。</param>
		/// <param name="value">条件值。</param>
		public void AddCondition(F member, object value)
		{
			this._conditions.Add(new Condition<F>(member, value));
		}

		/// <summary>
		/// 添加一个查询条件。
		/// </summary>
		/// <param name="member">条件成员。</param>
		/// <param name="@operator">条件操作符。</param>
		/// <param name="value">条件值。</param>
		public void AddCondition(F member, ConditionOperator @operator, object value)
		{
			this._conditions.Add(new Condition<F>(member, @operator, value));
		}

		/// <summary>
		/// 移除一个查询成员。
		/// </summary>
		/// <param name="member">需要移除的条件成员。</param>
		public void RemoveCondition(F member)
		{
			var conditions = this._conditions.Where(p => p.Member.Equals(member));

			foreach(var condition in conditions)
			{
				this._conditions.Remove(condition);
			}
		}

		/// <summary>
		/// 清空所有查询条件。
		/// </summary>
		public void ClearCondition()
		{
			this._conditions.Clear();
		}

		/// <summary>
		/// 获取一个值，指示当前条件是否包含指定的条件成员。
		/// </summary>
		/// <param name="member">条件成员。</param>
		/// <returns>如果包含指定的条件成员，则为 true；否则为 false。</returns>
		public bool ContainsCondition(F member)
		{
			return this._conditions.Any(p => p.Member.Equals(member));
		}

		/// <summary>
		/// 合并查询条件。
		/// </summary>
		/// <returns>合并后的查询条件。</returns>
		public ConditionCollection CombileCondition()
		{
			// 多个条件的处理方式
			var conditions = new ConditionCollection(this.CombineMode);

			foreach(var condition in this._conditions)
			{
				conditions.Add(condition);
			}

			return conditions;
		}

		#endregion

		#region 排序条件

		/// <summary>
		/// 添加一个排序成员。
		/// </summary>
		/// <param name="member">排序成员。</param>
		/// <param name="mode">排序方式。</param>
		public void AddSorting(S member, SortingMode mode)
		{
			if(this._sortings.Any(p => p.Member.Equals(member)))
				throw new InvalidOperationException("排序成员必须是唯一的。");

			this._sortings.Add(new Sorting<S>(member, mode));
		}

		/// <summary>
		/// 获取一个值，指示当前条件是否包含指定的排序成员。
		/// </summary>
		/// <param name="member">排序成员。</param>
		/// <returns>如果包含指定的排序成员，则为 true；否则为 false。</returns>
		public bool ContainsSorting(S member)
		{
			return this._sortings.Any(p => p.Member.Equals(member));
		}

		/// <summary>
		/// 移除一个排序成员。
		/// </summary>
		/// <param name="member">需要移除的排序成员。</param>
		public void RemoveSorting(S member)
		{
			var sorting = this._sortings.FirstOrDefault(p => p.Member.Equals(member));

			if(sorting != null)
				this._sortings.Remove(sorting);
		}

		/// <summary>
		/// 清空所有排序成员。
		/// </summary>
		public void ClearSorting()
		{
			this._sortings.Clear();
		}

		/// <summary>
		/// 合并排序成员。
		/// </summary>
		/// <returns>合并后的排序成员。</returns>
		public SortingCollection CombileSorting()
		{
			var sortings = new SortingCollection();

			foreach(var sorting in this._sortings)
			{
				sortings.Add(sorting);
			}

			return sortings;

		}

		#endregion

		#region 成员附加

		/// <summary>
		/// 添加一个附加成员。
		/// </summary>
		/// <param name="member">附加成员。</param>
		public void AddInclude(I member)
		{
			if(!this.ContainsInclude(member))
				this._includes.Add(member);
		}

		/// <summary>
		/// 移除一个附加成员。
		/// </summary>
		/// <param name="member">需要移除的附加成员。</param>
		public void RemoveInclude(I member)
		{
			if(this.ContainsInclude(member))
				this._includes.Remove(member);
		}

		/// <summary>
		/// 获取一个值，指示当前条件是否包含指定的附加成员。
		/// </summary>
		/// <param name="member">附加成员。</param>
		/// <returns>如果包含指定的附加成员，则为 true；否则为 false。</returns>
		public bool ContainsInclude(I member)
		{
			return this._includes.Contains(member);
		}

		/// <summary>
		/// 合并包含成员。
		/// </summary>
		/// <returns>合并后的包含成员。</returns>
		public IEnumerable<string> CombileInclude()
		{
			var includes = new List<string>();

			foreach(var include in this._includes)
			{
				var entry = EnumUtility.GetEnumEntry(include as Enum);
				var name = !string.IsNullOrEmpty(entry.Alias) ? entry.Alias : entry.Name;

				includes.Add(name);
			}

			return includes;
		}

		#endregion
	}

	public abstract class SearchParameter<F, S> : SearchParameter<F, S, EmptyEnum>, ISearchParameter<F, S> where F : struct where S : struct
	{

	}
}
